home *** CD-ROM | disk | FTP | other *** search
/ Light ROM 1 / LIGHT-ROM 1 (Amiga Library Services)(1994).iso / ffdisks / d941.lha / YAMFG / Source / YAMFG.English next >
Text File  |  1993-12-20  |  27KB  |  869 lines

  1. ; YAMFG 1.0 - ©1993 F.Delacroix- FreeWare
  2. ; written on HiSoft Devpac 3
  3.  
  4. ; all system includes were included at assembly time using the
  5. ; system.gs file of Devpac 3. If you use another assembly,just
  6. ; include them individually
  7.  
  8.     include    exec/execbase.i        ; some more includes: ExecBase struct
  9.     include    hardware/custom.i    ; custom hardware: for random numbers
  10.     include    libraries/reqtools.i    ; includes for reqtools.library
  11.     include    libraries/reqtools_lib.i
  12.  
  13. DEFAULT_WIDTH    EQU    20    ; useful constants: self-explanatory...
  14. DEFAULT_HEIGHT    EQU    20
  15. DEFAULT_MINES    EQU    40
  16. MAX_WIDTH    EQU    24
  17. MAX_HEIGHT    EQU    21
  18. UP    EQU    $4c        ; keys used to move the tank
  19. DOWN    EQU    $4d
  20. RIGHT    EQU    $4e
  21. LEFT    EQU    $4f
  22. STATUSX    EQU    4    ; coordinates for the status-line
  23. STATUSY    EQU    18
  24.  
  25.     move.l    4.w,a6
  26.     move.l    ThisTask(a6),a4    ;find my task (same as FindTask(0))
  27.     moveq    #0,d0
  28.     tst.l    pr_CLI(a4)    ; were we called from CLI ?
  29.     bne.s    FromCLI    ; yes,we were...
  30.     lea    pr_MsgPort(a4),a0    ; no: get the WBStartup message
  31.     jsr    _LVOWaitPort(a6)    ; sent by the Workbench
  32.     lea    pr_MsgPort(a4),a0
  33.     jsr    _LVOGetMsg(a6)
  34. FromCLI    move.l    d0,WBStarter    ; and store it (0 if from CLI)
  35.  
  36.     lea    ReqTools.Name(pc),a1    ; let's open the reqtools.library
  37.     moveq    #0,d0
  38.     jsr    _LVOOpenLibrary(a6)
  39.     move.l    d0,ReqTools.Base
  40.     beq    OutOfHere    ; no reqtools.library: exit program
  41.  
  42.     move.l    ReqTools.Base(pc),a0    ; and get other library bases from it
  43.     move.l    rt_IntuitionBase(a0),Intuition.Base
  44.     move.l    rt_GfxBase(a0),Graphics.Base
  45.  
  46.     lea    YAMFG.NewWindow(pc),a0    ; let's open the window
  47.     move.l    Intuition.Base(pc),a6
  48.     jsr    _LVOOpenWindow(a6)
  49.     move.l    d0,YAMFG.Window
  50.     beq    CloseReqTools    ; cannot open window !
  51.  
  52.     move.l    YAMFG.Window(pc),a0    ; let's attach the menues to the window
  53.     lea    Project.Menu(pc),a1
  54.     jsr    _LVOSetMenuStrip(a6)
  55.     tst.l    d0
  56.     beq    CloseWindow    ; failed ! (shouldn't occur)
  57.  
  58.     move.l    YAMFG.Window(pc),a0    ; store important data from our window
  59.     move.l    wd_RPort(a0),YAMFG.RastPort    ; RastPort for graphics
  60.     move.l    wd_UserPort(a0),YAMFG.UserPort    ; UserPort for messages
  61.     bra    NewGame    ; let's begin a new game...
  62.  
  63. WaitMessage
  64.     move.l    YAMFG.UserPort(pc),a0    ; let's wait for a message from
  65.     move.l    4.w,a6            ; Intuition to our window...
  66.     jsr    _LVOWaitPort(a6)
  67. NextMessage
  68.     move.l    YAMFG.UserPort(pc),a0    ; And get it!
  69.     move.l    4.w,a6
  70.     jsr    _LVOGetMsg(a6)
  71.     tst.l    d0
  72.     beq.s    WaitMessage    ; Was there actually one ?
  73.     move.l    d0,a1        ; Yeah !
  74.     move.l    im_Class(a1),d7        ; Store important fields:Class
  75.     move.w    im_Code(a1),d6        ; and Code
  76.     jsr    _LVOReplyMsg(a6)    ; then reply to Intuition
  77.     cmp.l    #IDCMP_CLOSEWINDOW,d7    ; Should we quit ?
  78.     beq    ClearMenus        ; Yes? Then go...
  79.     cmp.w    #IDCMP_RAWKEY,d7    ; Was a key pressed
  80.     bne    NoRawKey
  81.     btst    #IECODEB_UP_PREFIX,d6    ; ignore if a key was released
  82.     bne    NextMessage
  83.     tst.b    FinishFlag    ; was the game finished ?
  84.     bne    NewGame        ; yes? then begin a new one
  85.     move.w    MinerX(pc),d0    ; no: get the position of the tank
  86.     move.w    MinerY(pc),d1
  87.  
  88.     cmp.w    #UP,d6        ; Up ?
  89.     beq.s    GoUp
  90.     cmp.w    #DOWN,d6    ; Down ?
  91.     beq.s    GoDown
  92.     cmp.w    #RIGHT,d6    ; Right ?
  93.     beq.s    GoRight
  94.     cmp.w    #LEFT,d6    ; Or left ?
  95.     bne    NextMessage    ; None of that ?? then get next Message
  96.  
  97.     subq.w    #1,d0        ; 1 step left
  98.     bra.s    DirectionGot
  99. GoRight    addq.w    #1,d0        ; 1 step right
  100.     bra.s    DirectionGot
  101. GoDown    addq.w    #1,d1        ; 1 step down
  102.     bra.s    DirectionGot
  103. GoUp    subq.w    #1,d1        ; 1 step up
  104.  
  105. DirectionGot
  106.     bsr    CheckBounds    ; check if tank does not go out of bounds
  107.     bsr    MoveMiner    ; then move it
  108.     move.l    Width(pc),d0    ; Is tank on the right edge ?
  109.     subq.l    #1,d0
  110.     cmp.w    MinerX(pc),d0
  111.     bne.s    NoGoal
  112.     move.l    Height(pc),d0    ; Is it on the bottom ?
  113.     subq.l    #1,d0
  114.     cmp.w    MinerY(pc),d0
  115.     bne.s    NoGoal        ; yes ! The goal is reached ! (Congrats!)
  116.     lea    Won.MSG(pc),a0    ; Get winning message..
  117.     bra.s    EndOfGame    ; and end the game
  118.  
  119. NoGoal    moveq    #0,d0        ; Target not reached yet...
  120.     move.w    MinerY(pc),d0    ; Turn tank position into an offset for
  121.     mulu    Width+2(pc),d0    ; the mine array: offset=Width*Y+X
  122.     add.w    MinerX(pc),d0
  123.     lea    Mines.Array(pc),a2
  124.     tst.b    (a2,d0)        ; test if tank is on a mine
  125.     beq.s    ShowNumber    ; No!!
  126.  
  127.     lea    Lost.MSG(pc),a0    ; Uh-Oh: a mine !
  128. EndOfGame
  129.     st    FinishFlag    ; The game is finished
  130.     bsr    DisplayStatus    ; Display the end message (won or lost)
  131.     bsr    RevealMines    ; and display mine positions
  132.     bra    NextMessage    ; go back to loop
  133. NewGame
  134.     clr.b    FinishFlag    ; When a game begins,it is not finished yet
  135.     move.l    YAMFG.RastPort(pc),a1
  136.     moveq    #RP_JAM2,d0
  137.     move.l    Graphics.Base(pc),a6
  138.     jsr    _LVOSetDrMd(a6)    ; set drawmode to RP_JAM2 (uses both pens)
  139.     move.l    YAMFG.RastPort(pc),a1
  140.     moveq    #0,d0
  141.     jsr    _LVOSetAPen(a6)    ; select color 0
  142.     move.l    YAMFG.RastPort(pc),a1
  143.     move.l    #4,d0    ; draw a big rectangle to clear all the display
  144.     move.l    #12,d1
  145.     move.l    #396,d2
  146.     move.l    #196,d3
  147.     jsr    _LVORectFill(a6)
  148.     bsr    DrawMinesBorder    ; draw a border around play area
  149.     bsr    PlaceMines    ; Generate random mine positions
  150.     clr.w    MinerX    ; Place the tank in the upper left corner
  151.     clr.w    MinerY
  152.     bsr    ShowMiner    ; draw the tank
  153.  
  154. ShowNumber
  155.     lea    Mines.Array(pc),a2
  156.     moveq    #0,d0
  157.     move.w    MinerY(pc),d0    ; turn tank position into offset for table
  158.     mulu    Width+2(pc),d0
  159.     add.w    MinerX(pc),d0
  160.     add.l    d0,a2        ; tank emplacement within mine array
  161.     moveq    #0,d1
  162.     move.l    Width(pc),d3    ; d3=Width of play area
  163.     move.l    Height(pc),d4
  164.     move.l    d3,d5        ; d5=Width-1
  165.     subq.l    #1,d5
  166.     subq.l    #1,d4        ; d4=Height-1
  167.     move.l    d3,d6
  168.     neg.l    d6        ; d6=-Width
  169.     tst.w    MinerY        ; is tank on upper edge ?
  170.     beq.s    No9        ; yes? then don't test above tank!
  171.     tst.b    (a2,d6.l)    ; mine in position 8 ?
  172.     beq.s    No8        ; note: I follow these conventions within
  173.     addq.l    #1,d1        ; the source: 789
  174. No8    tst.w    MinerX        ;             4 6
  175.     beq.s    No7        ;             123
  176.     tst.b    -1(a2,d6.l)    ; if the array in tested position
  177.     beq.s    No7        ; (in order of appearance:8,7,9,4,6,1,2,3)
  178.     addq.l    #1,d1        ; is not zero, then there is a mine,and
  179. No7    cmp.w    MinerX(pc),d5    ; the mine counter (d1) is incremented
  180.     beq.s    No9        ; Of course,if the position does not make
  181.     tst.b    1(a2,d6.l)    ; a sense (if the tank is on an edge of
  182.     beq.s    No9        ; the play area),the position is not tested.
  183.     addq.l    #1,d1
  184. No9    tst.w    MinerX
  185.     beq.s    No4
  186.     tst.b    -1(a2)
  187.     beq.s    No4
  188.     addq.l    #1,d1
  189. No4    cmp.w    MinerX(pc),d5
  190.     beq.s    No6
  191.     tst.b    1(a2)
  192.     beq.s    No6
  193.     addq.l    #1,d1
  194. No6    cmp.w    MinerY(pc),d4
  195.     beq.s    No3
  196.     tst.w    MinerX
  197.     beq.s    No1
  198.     tst.b    -1(a2,d3)
  199.     beq.s    No1
  200.     addq.l    #1,d1
  201. No1    tst.b    (a2,d3)
  202.     beq.s    No2
  203.     addq.l    #1,d1
  204. No2    cmp.w    MinerX(pc),d5
  205.     beq.s    No3
  206.     tst.b    1(a2,d3)
  207.     beq.s    No3
  208.     addq.l    #1,d1
  209. No3
  210.     add.b    #'0',d1    ; turn mine counter into a displayable digit
  211.     move.b    d1,Mines.Number    ; and store it for printing
  212.     lea    MinesNumber.MSG(pc),a0    ; This is the 'Mines around' message
  213.     bsr    DisplayStatus    ; display it!
  214.     bra    NextMessage    ; next user action...
  215.  
  216. NoRawKey
  217.     cmp.l    #IDCMP_MENUPICK,d7    ; was a menu selected ?
  218.     bne    NextMessage    ; no: ignore that a strange message!
  219. DoNextSelect
  220.     move.w    d6,d0        ; this is the menu number given by Intuition
  221.     lea    Project.Menu(pc),a0    ; our menu strip
  222.     move.l    Intuition.Base(pc),a6
  223.     jsr    _LVOItemAddress(a6)    ; get address of selected MenuItem
  224.     move.l    d0,a5
  225.     tst.l    d0    ; was there one actually ?
  226.     beq    NextMessage    ; No: end of menu treatment
  227.     move.w    mi_NextSelect(a5),d6    ; store menunumber of next selected
  228.     move.l    mi_SIZEOF(a5),a1    ; This is a custom field in the item
  229.     cmp.l    #0,a1    ; structure: it points to the routine to execute..
  230.     beq    DoNextSelect    ; if there is one of course
  231.     jsr    (a1)    ; execute it !
  232.     bra.s    DoNextSelect    ; then process next menu selection
  233.  
  234. ClearMenus    ; Time to quit the game !!
  235.     move.l    YAMFG.Window(pc),a0    ; remove menues from our window
  236.     move.l    Intuition.Base(pc),a6
  237.     jsr    _LVOClearMenuStrip(a6)
  238. CloseWindow
  239.     move.l    YAMFG.Window(pc),a0    ; close the window
  240.     move.l    Intuition.Base(pc),a6
  241.     jsr    _LVOCloseWindow(a6)
  242. CloseReqTools
  243.     move.l    ReqTools.Base(pc),a1    ; close the reqtools.library
  244.     move.l    4.w,a6
  245.     jsr    _LVOCloseLibrary(a6)
  246. OutOfHere
  247.     move.l    WBStarter(pc),d1    ; were we called from Workbench ?
  248.     beq.s    BackToCLI    ; no: there is no more to be done
  249.     jsr    _LVOForbid(a6)    ; yes: we must reply to the WBStartup
  250.     move.l    d1,a1    ; message we received on start of the prog
  251.     move.l    4.w,a6        ; note that the Forbid() call is absolutely
  252.     jsr    _LVOReplyMsg(a6)    ; necessary.
  253. BackToCLI
  254.     moveq    #0,d0    ; so that CLI does not display strangest codes...
  255.     rts    ; This is the sad end ...
  256.  
  257. ; subroutine that initializes some display variables and draws the
  258. ; rectangular border and displays the target picture
  259. DrawMinesBorder
  260.     movem.l    d0-d1/a0-a1/a6,-(sp)
  261.     move.l    Width(pc),d0    ; Width in pixels=Width*16
  262.     lsl.l    #4,d0
  263.     move.l    Height(pc),d1    ; Height in pixels=Height*8
  264.     lsl.l    #3,d1
  265.     addq.l    #1,d0
  266.     addq.l    #1,d1
  267.     move.w    d0,Border.Right1    ; store these values for drawing the
  268.     move.w    d0,Border.Right2    ; border
  269.     move.w    d0,Border.Right3
  270.     move.w    d1,Border.Bot1
  271.     move.w    d1,Border.Bot2
  272.     move.w    d1,Border.Bot3
  273.     move.l    YAMFG.RastPort(pc),a0    ; the window RastPort
  274.     lea    YAMFG.Border(pc),a1    ; the Border structure
  275.     move.l    Width(pc),d0    ; Compute the PlayX variable to center
  276.     lsl.l    #3,d0    ; the playing field: PlayX=(400-Width*16)/2
  277.     neg.l    d0    ; PlayX=200-Width*8
  278.     add.l    #200,d0
  279.     move.l    d0,PlayX
  280.     move.l    Height(pc),d1    ; Compute the PlayY variable in a similar
  281.     lsl.l    #2,d1    ; way: PlayY=(200-Height*8)/2=100-Height*4
  282.     neg.l    d1
  283.     add.l    #100,d1
  284.     addq.l    #3,d1    ; and add 3 pixels
  285.     cmp.l    #STATUSY+4,d1    ; but do not overlap the Status Line
  286.     bge.s    NotTooLow    ; area !!
  287.     move.l    #STATUSY+4,d1    ; If it's the case,then lower it a bit
  288. NotTooLow
  289.     move.l    d1,PlayY
  290.     move.l    Intuition.Base(pc),a6
  291.     jsr    _LVODrawBorder(a6)    ; Draw the damn border
  292.     move.l    YAMFG.RastPort(pc),a0    ; Necessary for all graphic operations
  293.     lea    Target.Image,a1    ; The image structure for the target
  294.     move.l    Width(pc),d0    ; X Y positions of the target:
  295.     subq.l    #1,d0    ; in the lower right corner
  296.     lsl.l    #4,d0
  297.     add.l    PlayX(pc),d0
  298.     move.l    Height(pc),d1
  299.     subq.l    #1,d1
  300.     lsl.l    #3,d1
  301.     add.l    PlayY(pc),d1
  302.     jsr    _LVODrawImage(a6)    ; let Intuition draw it.
  303.     movem.l    (sp)+,d0-d1/a0-a1/a6
  304.     rts
  305.  
  306. ; this is the subroutine that randomly places the mines in the array
  307. ; It is NOT guaranteed that there is a way out if the mines are too
  308. ; numerous. The routine uses a classic FastRand() algorythm which takes
  309. ; the position of the raster as seed
  310. PlaceMines
  311.     movem.l    d0/d3-d5/a2,-(sp)
  312.     lea    Mines.Array(pc),a2    ; array to fill
  313.     move.l    Width(pc),d0
  314.     mulu    Height+2(pc),d0    ; Size of the array
  315.     move.l    d0,d3
  316.     subq.l    #1,d0    ; a dbra loop counts down to -1
  317. ClearMines
  318.     clr.b    (a2)+    ; wipe all mines from the array
  319.     dbra    d0,ClearMines
  320.     moveq    #0,d5
  321.     move.w    $DFF000+vhposr,d5    ; get the seed from the vhposr registr
  322.     lea    Mines.Array(pc),a2    ; restore a2
  323.     move.l    Mines(pc),d4    ; number of mines to place
  324.     cmp.l    d4,d3    ; is it possible ??
  325.     bgt.s    AnotherRandom    ; yes it is
  326.     move.l    d3,d4    ; there are far too many mines !! Reduce the number
  327.     subq.l    #4,d4    ; this is only for safety: who would want a game where
  328. AnotherRandom        ; every move is loss ?
  329.     add.l    d5,d5    ; This is the FastRand() routine that generates
  330.     bhi.s    .NoEOR    ; a seemingly random series of numbers
  331.     eor.l    #$1D872B41,d5    ; Why this number ? This is a good question.
  332. .NoEOR
  333.     moveq    #0,d0    ; divide the random number by the array size so that
  334.     move.w    d5,d0    ; the modulo reflects a valid position in the grid
  335.     divu    d3,d0
  336.     swap    d0
  337.     tst.w    d0    ; I don't want a mine in the upper left corner!
  338.     beq    AnotherRandom
  339.     tst.b    (a2,d0.w)    ; Is there already a mine there ?
  340.     bne.s    AnotherRandom    ; Yes?? Well use another offset
  341.     move.b    #1,(a2,d0.w)    ; No: well now there is one
  342.     subq    #1,d4    ; Was it the last mine to be placed ?
  343.     bne    AnotherRandom    ; No.
  344.     movem.l    (sp)+,d0/d3-d5/a2    ; Yes: restore registers and
  345.     rts    ; return
  346.  
  347. ; This displays the tank..
  348. ShowMiner
  349.     movem.l    d0-d1/a0-a1/a6,-(sp)
  350.     move.l    YAMFG.RastPort(pc),a0
  351.     lea    Tank.Image,a1    ; Image structure for the tank
  352.     moveq    #0,d0
  353.     move.l    d0,d1
  354.     move.w    MinerX(pc),d0
  355.     move.w    MinerY(pc),d1
  356.     lsl.l    #4,d0
  357.     lsl.l    #3,d1
  358.     add.l    PlayX(pc),d0    ; X=PlayX+MinerX*16
  359.     add.l    PlayY(pc),d1    ; Y=PlayY+MinerY*8
  360.     move.l    Intuition.Base(pc),a6
  361.     jsr    _LVODrawImage(a6)    ; Draw it. Easy no?
  362.     movem.l    (sp)+,d0-d1/a0-a1/a6
  363.     rts
  364.  
  365. ; This checks whether the tank has gone out of bounds,in which case it is
  366. ; placed back on the edge of the grid. This routine is called with the
  367. ; newly demanded position in D0 and D1 (X and Y respectively).
  368. CheckBounds
  369.     ext.l    d0    ; Turn X position into a longword
  370.     cmp.l    Width(pc),d0    ; Too far on the right ?
  371.     blt.s    NotRightEdge
  372.     move.l    Width(pc),d0
  373.     subq.l    #1,d0
  374. NotRightEdge
  375.     tst.l    d0        ; Too far on the left ?
  376.     bge.s    NotLeftEdge
  377.     moveq    #0,d0
  378. NotLeftEdge
  379.     ext.l    d1    ; Turn Y position into a longword
  380.     tst.l    d1        ; Too far up ?
  381.     bge.s    NotUpEdge
  382.     moveq    #0,d1
  383. NotUpEdge
  384.     cmp.l    Height(pc),d1    ; Too far down ?
  385.     blt.s    NoDownEdge
  386.     move.l    Height(pc),d1
  387.     subq.l    #1,d1
  388. NoDownEdge
  389.     rts
  390.  
  391. ; This routine erases the tank image and then draw it at the position
  392. ; given by D0 and D1 (X and Y).It also updates the MinerX and MinerY vars.
  393. MoveMiner
  394.     bsr.s    EraseMiner
  395.     move.w    d0,MinerX
  396.     move.w    d1,MinerY
  397.     bra    ShowMiner
  398.  
  399. ; This erases the tank image by printing two spaces in color 3
  400. EraseMiner
  401.     movem.l    d0-d1/a0-a1/a6,-(sp)
  402.     move.l    YAMFG.RastPort(pc),a1
  403.     moveq    #0,d0    ; X=PlayX+MinerX*16
  404.     move.l    d0,d1    ; Y=PlayY+MinerY*8
  405.     move.w    MinerX(pc),d0
  406.     move.w    MinerY(pc),d1
  407.     lsl.l    #4,d0
  408.     lsl.l    #3,d1
  409.     add.l    PlayX(pc),d0
  410.     add.l    PlayY(pc),d1
  411.     addq.l    #6,d1    ; Add 6 to the Y position to get the baseline of the
  412.     move.l    Graphics.Base(pc),a6    ; standard topaz font.
  413.     jsr    _LVOMove(a6)    ; Move the graphic cursor there
  414.     move.l    YAMFG.RastPort(pc),a1
  415.     moveq    #3,d0    ; set the B pen to color 3 (orange or blue on
  416.     jsr    _LVOSetBPen(a6)    ; normal-coloured workbenchs)
  417.     move.l    YAMFG.RastPort(pc),a1
  418.     moveq    #RP_JAM2,d0    ; set the drawmode to RP_JAM2 so that
  419.     jsr    _LVOSetDrMd(a6)    ; spaces are truly made blue
  420.     lea    Space.Text(pc),a0    ; The spaces
  421.     move.l    YAMFG.RastPort(pc),a1
  422.     moveq    #2,d0    ; there are two of them
  423.     jsr    _LVOText(a6)
  424.     movem.l    (sp)+,d0-d1/a0-a1/a6
  425.     rts    ; That's it
  426.  
  427. ; This routine is used to erase the status line. It is called by DisplayStatus
  428. EraseStatus
  429.     movem.l    d0-d3/a0-a1/a6,-(sp)
  430.     move.l    YAMFG.RastPort(pc),a1
  431.     moveq    #RP_JAM2,d0
  432.     move.l    Graphics.Base(pc),a6
  433.     jsr    _LVOSetDrMd(a6)    ; Drawmode to RP_JAM2
  434.     move.l    YAMFG.RastPort(pc),a1
  435.     moveq    #0,d0    ; A pen to color 0
  436.     jsr    _LVOSetAPen(a6)
  437.     move.l    YAMFG.RastPort(pc),a1
  438.     move.l    #STATUSX,d0    ; coordinates for the rectangle that will
  439.     move.l    #STATUSY-6,d1    ; be drawn over the status line
  440.     move.l    #STATUSX+40*8,d2
  441.     move.l    #STATUSY+2,d3
  442.     jsr    _LVORectFill(a6)    ; draw the rectangle
  443.     movem.l    (sp)+,d0-d3/a0-a1/a6
  444.     rts
  445.  
  446. ; This routine displays a message in the status line,which is first cleared.
  447. ; On calling,A0 must be loaded with a pointer to the message to be displayed.
  448. DisplayStatus:            ;DisplayStatus(Message)(A0)
  449.     movem.l    d0-d1/a0-a2/a6,-(sp)
  450.     bsr    EraseStatus    ; First erase the status line
  451.     move.l    a0,a2    ; Save the message pointer (A2 is guaranteed to
  452.     move.l    YAMFG.RastPort(pc),a1    ; be preserved by library routines)
  453.     moveq    #RP_JAM1,d0
  454.     move.l    Graphics.Base(pc),a6
  455.     jsr    _LVOSetDrMd(a6)    ; drawmode to RP_JAM1: only the A pen is used
  456.     move.l    YAMFG.RastPort(pc),a1
  457.     moveq    #1,d0
  458.     jsr    _LVOSetAPen(a6)    ; A Pen to color 1 (normally black or white)
  459.     move.l    YAMFG.RastPort(pc),a1
  460.     move.l    #STATUSX,d0    ; Coordinates of the status line
  461.     move.l    #STATUSY,d1
  462.     jsr    _LVOMove(a6)    ; move the graphic cursor there
  463.     move.l    a2,a0
  464. .LenLoop        ; count the length of the message
  465.     tst.b    (a2)+    ; this is required for the Text() function
  466.     bne    .LenLoop
  467.     sub.l    a0,a2
  468.     subq.l    #1,a2
  469.     move.l    a2,d0
  470.     move.l    YAMFG.RastPort(pc),a1
  471.     jsr    _LVOText(a6)    ; print the text
  472.     movem.l    (sp)+,d0-d1/a0-a2/a6
  473.     rts
  474.  
  475. ; This routine reveals where the mines were placed,it is called when the
  476. ; game has ended (the player has won or lost)
  477. RevealMines
  478.     movem.l    d0-d3/a0-a2/a6,-(sp)
  479.     lea    Mines.Array(pc),a2    ; The mines grid
  480.     moveq    #-1,d2        ; The current position in the array
  481.     move.l    Intuition.Base(pc),a6
  482.     move.l    Width(pc),d3
  483.     mulu    Height+2(pc),d3    ; d3 is the size of the array
  484. RevealLoop
  485.     addq.l    #1,d2    ; increment position
  486.     cmp.l    d3,d2    ; have we reached the end of the array ?
  487.     beq.s    EndOfReveal    ; yes...then go.
  488.     tst.b    (a2)+    ; is there a mine here ?
  489.     beq.s    RevealLoop    ; No, check next position
  490.     move.l    d2,d0    ; yes! Its position is in D0
  491.     divu    Width+2(pc),d0    ; this is to split X and Y positions
  492.     moveq    #0,d1    ; X position (the modulo of the division) is in D0
  493.     move.w    d0,d1    ; and the Y is in D1 (the quotient of the division)
  494.     clr.w    d0
  495.     swap    d0
  496.     move.l    YAMFG.RastPort(pc),a0
  497.     lea    Mine.Image,a1    ; Image structure for a mine
  498.     lsl.l    #4,d0    ; Turn X and Y positions in the grid into true
  499.     lsl.l    #3,d1    ; graphic places
  500.     add.l    PlayX(pc),d0
  501.     add.l    PlayY(pc),d1
  502.     jsr    _LVODrawImage(a6)    ; Draw a mine
  503.     bra    RevealLoop    ; check some more positions
  504. EndOfReveal
  505.     movem.l    (sp)+,d0-d3/a0-a2/a6    ; all mines were displayed,our job
  506.     rts    ; is finished
  507.  
  508. ; This routine is called when the corresponding menu is selected
  509. QuitYAMFG
  510.     addq.l    #4,sp    ; There is no return for this routine
  511.     bra    ClearMenus    ; We quit!
  512.  
  513. ; This is called when the player has chosen 'About' in the menues
  514. ShowAbout
  515.     movem.l    d0-d1/a0-a4/a6,-(sp)
  516.     lea    About.Body(pc),a1    ; Main message
  517.     lea    About.Gad(pc),a2    ; Text for the gadget
  518.     suba.l    a3,a3    ; No ReqInfo structure
  519.     move.l    a3,a4    ; And no formatting things
  520.     lea    About.TagList(pc),a0    ; specific TagList
  521.     move.l    ReqTools.Base(pc),a6    ; Let the great reqtools.library
  522.     jsr    _LVOrtEZRequestA(a6)    ; do it..
  523.     movem.l    (sp)+,d0-d1/a0-a4/a6
  524.     rts
  525.  
  526. ; This is when the user wants to change the number of mines (with the menu)
  527. ModifyMines
  528.     lea    Mines(pc),a1    ; Variable containing the number of mines
  529.     lea    HowManyMines.Title(pc),a2    ; Title for the requester
  530.     suba.l    a3,a3    ; No ReqInfo structure
  531.     lea    Mines.TagList(pc),a0    ; but some tags...
  532.     move.l    ReqTools.Base(pc),a6    ; Request the number of mines
  533.     jsr    _LVOrtGetLongA(a6)
  534.     tst.l    d0    ; has the user entered a valid number ?
  535.     bne.s    NewMines    ; yes, go for a new game
  536.     rts    ; no,the requester was canceled
  537.  
  538. ; This user wants to change the width of the playfield
  539. ChangeWidth
  540.     lea    Width(pc),a1    ; Variable for the width
  541.     lea    Width.Title(pc),a2    ; Title of the requester
  542.     sub.l    a3,a3    ; No ReqInfo structure
  543.     lea    Width.TagList(pc),a0    ; some tags...
  544.     move.l    ReqTools.Base(pc),a6
  545.     jsr    _LVOrtGetLongA(a6)    ; Get new width
  546.     tst.l    d0
  547.     bne.s    NewWidth    ; New game if it is valid
  548.     rts    ; return if the requester was canceled
  549. NewMines    ; this is a branch for the routines that require a new
  550. NewWidth    ; game to be started
  551. NewHeight
  552.     addq.l    #4,sp    ; cancel the return address on the stack
  553.     bra    NewGame    ; and branch to the main program
  554.  
  555. ; This is exactly the same routine as ChangeWidth(),I don't think comments
  556. ; are needed.
  557. ChangeHeight
  558.     lea    Height(pc),a1
  559.     lea    Height.Title(pc),a2
  560.     sub.l    a3,a3
  561.     lea    Height.TagList(pc),a0
  562.     move.l    ReqTools.Base(pc),a6
  563.     jsr    _LVOrtGetLongA(a6)
  564.     tst.l    d0
  565.     bne.s    NewHeight
  566.     rts
  567.  
  568. ; This part contains some data for windows,menus,messages,and miscellane-
  569. ; ous little things.
  570. YAMFG.NewWindow    ; this is the NewWindow structure
  571.     dc.w    120,0    ; XY origin
  572.     dc.w    400,200    ; Width and Height in pixels
  573.     dc.b    0,1    ; FrontPen and BackPen colors
  574.     dc.l    IDCMP_CLOSEWINDOW!IDCMP_RAWKEY!IDCMP_MENUPICK
  575. ; The above line contains IDCMP flags, a message will be sent by intuition
  576. ; to our program when such events occur.
  577.     dc.l    WINDOWDRAG!WINDOWDEPTH!WINDOWCLOSE!ACTIVATE!NOCAREREFRESH
  578. ; This are standard window flags. There is no special strange flag,they
  579. ; are self-explanatory,thus there is no need for further explanations,you
  580. ; should understand these by yourself, so there is no need for any further
  581. ; comments, so why should I bore you to death with this ?
  582.     dc.l    0    ; No gadgets on that window
  583.     dc.l    0    ; No custom CheckMark (we don't even use a checkmark)
  584.     dc.l    YAMFG.WindowName    ; Name for our window
  585.     dc.l    0    ; Screen: we will just use the Workbench screen
  586.     dc.l    0    ; Bitmap: No bitmap.
  587.     dc.w    400,200    ; Minimum dimensions (useless in our case)
  588.     dc.w    400,200    ; Maximum dimensions (idem)
  589.     dc.w    WBENCHSCREEN    ; yes,the Workbench screen
  590.  
  591. YAMFG.Border    ; Border structures for the rectangle around the play area
  592.     dc.w    -1,-1    ; XY origin
  593.     dc.b    1,0,RP_JAM1,3    ; FontPen,BackPen,DrawMode,Number of vectors
  594.     dc.l    YAMFG.Vectorsa,YAMFG.Borderb    ; Vectors,Next border struct
  595. YAMFG.Borderb
  596.     dc.w    -1,-1        ; we use two linked border structures in
  597.     dc.b    2,0,RP_JAM1,3    ; order to create a simi-3D effect (one side
  598.     dc.l    YAMFG.Vectorsb,0    ; is drawn in white,the other black)
  599.  
  600. YAMFG.Vectorsa    ; This are the XY coordinates for the vectors of the firs
  601.     dc.w    0    ; border. Some fields will be altered by the program
  602. Border.Bot1
  603.     dc.w    DEFAULT_HEIGHT*8+1
  604.     dc.w    0,0
  605. Border.Right1
  606.     dc.w    DEFAULT_WIDTH*16+1,0
  607.  
  608. YAMFG.Vectorsb    ; The same for the second border
  609. Border.Right2
  610.     dc.w    DEFAULT_WIDTH*16+1,1
  611. Border.Right3
  612.     dc.w    DEFAULT_WIDTH*16+1
  613. Border.Bot2
  614.     dc.w    DEFAULT_HEIGHT*8+1
  615.     dc.w    1
  616. Border.Bot3
  617.     dc.w    DEFAULT_HEIGHT*8+1
  618.  
  619. Project.Menu    ; This is the menu structure for the project menu
  620.     dc.l    Options.Menu    ; Next menu: the 'Options' menu
  621.     dc.w    0,0    ; LeftEdge and TopEdge
  622.     dc.w    63,0    ; Width and Height (Height is unused)
  623.     dc.w    MENUENABLED    ; Flags: the menu is enabled
  624.     dc.l    Project.Name    ; guess what this is
  625.     dc.l    About.MenuItem    ; First item for that menu
  626.     dc.w    0,0,0,0    ; mysterious Intuition variables
  627.  
  628. About.MenuItem    ; MenuItem structure for the 'About' Item
  629.     dc.l    Quit.MenuItem    ; Next Item
  630.     dc.w    0,0    ; LeftEdge,TopEdge
  631.     dc.w    104,8    ; Width,Height
  632.     dc.w    ITEMTEXT!COMMSEQ!ITEMENABLED!HIGHCOMP    ; menu flags:
  633. ; ITEMTEXT means that an IntuiText structure will be used (it could have been
  634. ; an Image),COMMSEQ means there will be a keyboard shortcut,ITEMENABLED means
  635. ; that the item can actually be selected,HIGHCOMP tells Intuition to inverse
  636. ; the colors of the menu when the mouse pointer is on it
  637.     dc.l    0    ; No Mutual-Exclude
  638.     dc.l    About.IText    ; Render: an IntuiText structure
  639.     dc.l    0    ; No render for selected state
  640.     dc.b    'A'    ; Keyboard shortcut
  641.     dc.b    0    ; This is just a fill byte to make the address even
  642.     dc.l    0    ; No SubItem list
  643.     dc.w    MENUNULL    ; will be filled by Intuition for extended
  644. ; selection
  645.     dc.l    ShowAbout    ; This is a custom field,used by the prog to
  646. ; determine which routine is to be executed when the menu is selected
  647. About.IText    ; This is an IntuiText structure for rendering the MenuItem
  648.     dc.b    3,1,RP_COMPLEMENT,0    ; DetailPen,BlockPen,DrawMode,FillByte
  649.     dc.w    0,0    ; LeftEdge,TopEdge
  650.     dc.l    0    ; No custom font
  651.     dc.l    About.MSG    ; Message
  652.     dc.l    0    ; No more IntuiText structure
  653.  
  654. ; The other Menu and MenuItem structures are made the same way,it would be a
  655. ; waste of time to describe them all.
  656.  
  657. Quit.MenuItem
  658.     dc.l    0
  659.     dc.w    0,8
  660.     dc.w    104,8
  661.     dc.w    ITEMTEXT!COMMSEQ!ITEMENABLED!HIGHCOMP
  662.     dc.l    0
  663.     dc.l    Quit.IText
  664.     dc.l    0
  665.     dc.b    'Q'
  666.     dc.b    0
  667.     dc.l    0
  668.     dc.w    MENUNULL
  669.     dc.l    QuitYAMFG
  670. Quit.IText
  671.     dc.b    3,1,RP_COMPLEMENT,0
  672.     dc.w    0,0
  673.     dc.l    0
  674.     dc.l    Quit.MSG
  675.     dc.l    0
  676.  
  677. Options.Menu
  678.     dc.l    0
  679.     dc.w    70,0
  680.     dc.w    63,0
  681.     dc.w    MENUENABLED
  682.     dc.l    Options.Name
  683.     dc.l    Mines.MenuItem
  684.     dc.w    0,0,0,0
  685.  
  686. Mines.MenuItem
  687.     dc.l    Width.MenuItem
  688.     dc.w    0,0
  689.     dc.w    184,8
  690.     dc.w    ITEMTEXT!COMMSEQ!ITEMENABLED!HIGHCOMP
  691.     dc.l    0
  692.     dc.l    Mines.IText
  693.     dc.l    0
  694.     dc.b    'M'
  695.     dc.b    0
  696.     dc.l    0
  697.     dc.w    MENUNULL
  698.     dc.l    ModifyMines
  699. Mines.IText
  700.     dc.b    3,1,RP_COMPLEMENT,0
  701.     dc.w    0,0
  702.     dc.l    0
  703.     dc.l    Mines.MSG
  704.     dc.l    0
  705.  
  706. Width.MenuItem
  707.     dc.l    Height.MenuItem
  708.     dc.w    0,8
  709.     dc.w    184,8
  710.     dc.w    ITEMTEXT!COMMSEQ!ITEMENABLED!HIGHCOMP
  711.     dc.l    0
  712.     dc.l    Width.IText
  713.     dc.l    0
  714.     dc.b    'W'
  715.     dc.b    0
  716.     dc.l    0
  717.     dc.w    MENUNULL
  718.     dc.l    ChangeWidth
  719. Width.IText
  720.     dc.b    3,1,RP_COMPLEMENT,0
  721.     dc.w    0,0
  722.     dc.l    0
  723.     dc.l    Width.MSG
  724.     dc.l    0
  725.  
  726. Height.MenuItem
  727.     dc.l    0
  728.     dc.w    0,16
  729.     dc.w    184,8
  730.     dc.w    ITEMTEXT!COMMSEQ!ITEMENABLED!HIGHCOMP
  731.     dc.l    0
  732.     dc.l    Height.IText
  733.     dc.l    0
  734.     dc.b    'H'
  735.     dc.b    0
  736.     dc.l    0
  737.     dc.w    MENUNULL
  738.     dc.l    ChangeHeight
  739. Height.IText
  740.     dc.b    3,1,RP_COMPLEMENT,0
  741.     dc.w    0,0
  742.     dc.l    0
  743.     dc.l    Height.MSG
  744.     dc.l    0
  745.  
  746. About.TagList    ; The tags for the about requester
  747.     dc.l    RT_IDCMPFlags,IDCMP_MOUSEBUTTONS!INACTIVEWINDOW
  748. ; Some more IDCMP flags to react on
  749.     dc.l    RTEZ_Flags,EZREQF_CENTERTEXT    ; Center Text in window
  750.     dc.l    TAG_END
  751.  
  752. Mines.TagList    ;Tags for the number of mines requester
  753.     dc.l    RTGL_Min,1    ; Minimum 1
  754.     dc.l    RTGL_Max,100    ; Maximum 100
  755.     dc.l    TAG_END
  756.  
  757. Width.TagList    ; For the width requester
  758.     dc.l    RTGL_Min,4    ; Minimum 4
  759.     dc.l    RTGL_Max,MAX_WIDTH    ; Maximum
  760.     dc.l    TAG_END
  761.  
  762. Height.TagList    ; For the height requester
  763.     dc.l    RTGL_Min,4    ; Minimum
  764.     dc.l    RTGL_Max,MAX_HEIGHT    ; Maximum
  765.     dc.l    TAG_END
  766.  
  767. Project.Name    ; No need for comments
  768.     dc.b    'Project',0
  769. About.MSG
  770.     dc.b    'About...',0
  771. Quit.MSG
  772.     dc.b    'Quit',0
  773. Options.Name
  774.     dc.b    'Options',0
  775. Mines.MSG
  776.     dc.b    'Number of mines...',0
  777. Width.MSG
  778.     dc.b    'Width...',0
  779. Height.MSG
  780.     dc.b    'Height...',0
  781.  
  782. YAMFG.WindowName
  783.     dc.b    'YAMFG 1.0 © 1993 F.Delacroix -FreeWare',0
  784. ReqTools.Name
  785.     dc.b    'reqtools.library',0    ; Name of the reqtools.library
  786. Space.Text
  787.     dc.b    '  '    ; Used to erase the tank image
  788. Lost.MSG
  789.     dc.b    'You blew up ! Press a key...',0
  790. MinesNumber.MSG
  791.     dc.b    'Number of mines around you:'
  792. Mines.Number
  793.     dc.b    '0',0
  794. Won.MSG    dc.b    'Congratulations! You''ve reached the goal!',0
  795.  
  796. About.Body    ; The about message,please dont change this.
  797.     dc.b    'YAMFG 1.0 by F.Delacroix - FreeWare',10,10
  798.     dc.b    'This program may not be used for any profit',10
  799.     dc.b    'To contact me,write to:',10
  800.     dc.b    'Frédéric DELACROIX',10
  801.     dc.b    '5 rue d''Artres',10
  802.     dc.b    '59269 QUERENAING, FRANCE',0
  803. About.Gad
  804.     dc.b    'Ah-ha.',0
  805.  
  806. HowManyMines.Title
  807.     dc.b    'How many mines ?',0
  808. Width.Title
  809.     dc.b    'New width ?',0
  810. Height.Title
  811.     dc.b    'New height ?',0
  812.  
  813. WBStarter    dc.l    0    ; WBStartup received (0 if from CLI)
  814. Graphics.Base    dc.l    0    ; Base of the graphics.library
  815. Intuition.Base    dc.l    0    ; Base of intuition.library
  816. ReqTools.Base    dc.l    0    ; Base of the great reqtools.library
  817. YAMFG.Window    dc.l    0    ; Window structure (not NewWindow)
  818. YAMFG.RastPort    dc.l    0    ; RastPort for our window
  819. YAMFG.UserPort    dc.l    0    ; UserPort for it
  820. Mines    dc.l    DEFAULT_MINES    ; Number of mines
  821. MinerX    dc.w    0    ; X position of the tank (from 0 to width-1)
  822. MinerY    dc.w    0    ; Y position of the tank (from 0 to height-1)
  823. Width    dc.l    DEFAULT_WIDTH    ; Width (in columns)
  824. Height    dc.l    DEFAULT_HEIGHT    ; Height (in lines)
  825. PlayX    dc.l    0    ; Graphic offset for the playfield
  826. PlayY    dc.l    0
  827. Mines.Array    dcb.b    MAX_WIDTH*MAX_HEIGHT,0    ; Array containing the posi-
  828. ; tions of the mines. Not that it may be that only a part of it is used as
  829. ; Width and Height may not be equal to MAX_WIDTH and MAX_HEIGHT
  830. FinishFlag    dc.b    0    ; Flag set when the game is over
  831.  
  832.     section    Images,DATA_C
  833. ; These are some structures that need to be in CHIP-ram:
  834. Tank.Image    ; Image structure for the tank
  835.     dc.w    0,0    ; LeftEdge,TopEdge
  836.     dc.w    16,8    ; Width,Height
  837.     dc.w    2    ; Depth: 4 colours
  838.     dc.l    Tank.ImageData    ; Data for the picture
  839.     dc.b    $0003,$0000    ; Patterns used for rendering in bitplanes
  840.     dc.l    0    ; Next Image structure:none
  841. Tank.ImageData
  842.     dc.w    $0000,$001F,$0000,$7FFE,$FFFF,$FFFF,$FFFF,$7FFE
  843. ; Data for the first bitplane
  844.     dc.w    $07C0,$0FE0,$0FE0,$7FFE,$FFFF,$8001,$7FFE,$0000
  845. ; Data for the second bitplane
  846.  
  847. Mine.Image    ; Image structure for a mine
  848.     dc.w    0,0
  849.     dc.w    16,8
  850.     dc.w    2
  851.     dc.l    Mine.ImageData
  852.     dc.b    $0001,$0000
  853.     dc.l    0
  854. Mine.ImageData
  855.     dc.w    $0000,$0000,$0000,$0000,$0FF0,$7FFE,$7FFE,$0000
  856. ; Only one bitplane here
  857.  
  858. Target.Image    ; Image structure for the target
  859.     dc.w    0,0
  860.     dc.w    16,8
  861.     dc.w    2
  862.     dc.l    Target.ImageData
  863.     dc.b    $0003,$0000
  864.     dc.l    0
  865. Target.ImageData
  866.     dc.w    $07E0,$0FF0,$1FF8,$3E7C,$3E7C,$1FF8,$0FF0,$07E0
  867.     dc.w    $07E0,$0C30,$1818,$318C,$318C,$1818,$0C30,$07E0
  868.  
  869.